﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Data.Objects;

namespace BL.BetterControls
{

    [Serializable]
    public class _MenuData
    {
        public Guid NodeId { get; set; }
        public Guid? NodeParentId { get; set; }
        public String NodeName { get; set; }
        public String NodeToolTip { get; set; }
        public String NodePath { get; set; }
        public String NodeNavUrl { get; set; }
        public String NodeTarget { get; set; }
        public Int32 NodeLevel { get; set; }

        public _MenuData()
        {
        }

        public _MenuData(Guid nodeId, Guid? nodeParentId, String nodeName, String nodeToolTip, String nodePath, String nodeNavUrl, String nodeTarget, Int32 nodeLevel)
        {
            NodeId = nodeId;
            NodeParentId = nodeParentId;
            NodeName = nodeName;
            NodeToolTip = nodeToolTip;
            NodePath = nodePath;
            NodeNavUrl = nodeNavUrl;
            NodeTarget = nodeTarget;
            NodeLevel = NodeLevel;
        }
    }
    
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:_Menu runat=server></{0}:_Menu>")]
    public class _Menu : WebControl, IPostBackEventHandler
    {
        public delegate void MenuClick(object sender, EventArgs e);
        public event MenuClick Click;
        

        private List<_MenuData> MenuData { get { return ViewState["MenuData"] != null ? (List<_MenuData>)ViewState["MenuData"] : null; } set { ViewState["MenuData"] = value; } }
        public string SelectedPath { get { return ViewState["SelectedPath"] != null ? (string)ViewState["SelectedPath"] : ""; } set { ViewState["SelectedPath"] = value; } }
        private Guid? SelectedParentId { get { return ViewState["SelectedParentId"] != null ? (Guid?)ViewState["SelectedParentId"] : null; } set { ViewState["SelectedParentId"] = value; } }
        public Guid SelectedId { get { return ViewState["SelectedId"] != null ? (Guid)ViewState["SelectedId"] : Guid.Empty; } set { ViewState["SelectedId"] = value; } }
        public Guid? RootId { get { return ViewState["RootId"] != null ? (Guid?)ViewState["RootId"] : null; } }
        public string SelectedName { get { return ViewState["SelectedName"] != null ? (string)ViewState["SelectedName"] : ""; } set { ViewState["SelectedName"] = value; } }

        #region propsettings
        public int StartLevel { get { return ViewState["StartLevel"] != null ? (int)ViewState["StartLevel"] : 1; } set { ViewState["StartLevel"] = value; } }
        public int HideAfterLevel { get { return ViewState["HideAfterLevel"] != null ? (int)ViewState["HideAfterLevel"] : 4; } set { ViewState["HideAfterLevel"] = value; } }
        /// <summary>
        /// Ignors NodeNavUrl and only post selected to current page if false and NodeNavUrl != null/"" menu opens the url
        /// </summary>
        public bool ActAsSelectMenu { get { return ViewState["ActAsSelectMenu"] != null ? (bool)ViewState["ActAsSelectMenu"] : false; } set { ViewState["ActAsSelectMenu"] = value; } }
        #endregion

        public List<_MenuData> GetMenuData()
        {
            return MenuData;
        }

        public void LoadMenu(List<_MenuData> menuData)
        {
            LoadMenu(menuData, "", null);
        }
        

        public void LoadMenu(List<_MenuData> menuData, string selectedPath)
        {
             LoadMenu(menuData, selectedPath, null);
        }

        public void LoadMenu(List<_MenuData> menuData, Guid? rootId)
        {
            LoadMenu(menuData, "", rootId);
        }

        public void LoadMenu(List<_MenuData> menuData, string selectedPath, Guid? rootId)
        {
            MenuData = menuData;
            SelectedPath = selectedPath;
            ViewState["RootId"] = rootId;
            SetSelectedProperties();
            //LoadMenu();

            //Måste sätta en del properties här från vald meny
        }

        public void LoadMenu(List<_MenuData> menuData, Guid selectedId, Guid? rootId)
        {
            ViewState["RootId"] = rootId;
            MenuData = menuData;
            _MenuData MD = MenuData.FirstOrDefault(q => q.NodeId == selectedId);

            if (MD != null)
            {
                SelectedPath = MD.NodePath;
                SelectedId = MD.NodeId;
                SelectedParentId = MD.NodeParentId;
                SelectedName = MD.NodeName;
            }
            //LoadMenu();
        }

        private void SetSelectedProperties()
        {

            _MenuData MD = null;

            if(string.IsNullOrEmpty(SelectedPath))
                MD =  MenuData.FirstOrDefault();
            else
                MD =  MenuData.FirstOrDefault(q => q.NodePath == SelectedPath);

            if (MD != null)
            {
                SelectedPath = MD.NodePath;
                SelectedId = MD.NodeId;
                SelectedParentId = MD.NodeParentId;
                SelectedName = MD.NodeName;
            }

        }

        private void LoadMenu()
        {

            this.Controls.Clear();

            HtmlGenericControl DIV = new HtmlGenericControl("div");
            if (StartLevel > 0)
            {
                DIV.Attributes.Add("class", "menu noroots");
            }
            else
            {
                DIV.Attributes.Add("class", "menu");
            }

            HtmlGenericControl UL = new HtmlGenericControl("ul");
            UL.ID = "menu";

            if (StartLevel > 0)
            {
                foreach (_MenuData row in MenuData.Where(q => q.NodeLevel == StartLevel))
                {
                    UL.Controls.Add(PopulateMenuItems(row, row.NodeId, UL, null, null));
                }
            }
            else
            {
                foreach (_MenuData row in MenuData.Where(q => q.NodeParentId == RootId))
                {
                    UL.Controls.Add(PopulateMenuItems(row, row.NodeId, UL, null, null));
                }
            }



            DIV.Controls.Add(UL);
            this.Controls.Add(DIV);

        }

        private HtmlGenericControl PopulateMenuItems(_MenuData data, Guid? parentId, HtmlGenericControl parentUL, HtmlGenericControl parentDIV, HtmlGenericControl parentLI)
        {
            HtmlGenericControl LI = new HtmlGenericControl("li");
            HtmlGenericControl DIV = new HtmlGenericControl("div");
            HtmlAnchor HA = new HtmlAnchor();
            HtmlGenericControl UL = new HtmlGenericControl("ul");

            HA.InnerText = data.NodeName;
            HA.Title = data.NodeToolTip;
            
            if (ActAsSelectMenu || string.IsNullOrEmpty(data.NodeNavUrl))
            {
                HA.HRef = Page.ClientScript.GetPostBackClientHyperlink(this, data.NodePath.ToString());
            }
            else
            {
                HA.HRef = data.NodeNavUrl;
                HA.Target = string.IsNullOrEmpty(data.NodeTarget) ? "self" : data.NodeTarget;
            }
            
            //OM det är en Root
            if (data.NodeLevel == StartLevel)
            {
                LI.Attributes["class"] += " root";
                DIV.Attributes["class"] += " root";
            }
            else if (data.NodeLevel > (StartLevel + 1) && data.NodeLevel <= HideAfterLevel)
            {
                LI.Attributes["class"] += " indent";
            }

            //Om Root är vald
            if (data.NodeLevel == StartLevel && data.NodeId == SelectedId)
            {
                parentUL.Attributes["class"] += " parent";
            }
            //Om parent till vald
            if (data.NodeId == SelectedParentId)
            {
                LI.Attributes["class"] += " parent";
            }
            //Om node är vald
            if (data.NodeId == SelectedId)
            {
                LI.Attributes["class"] += " child";
                DIV.Attributes["class"] += " selected";
            }
            //Om node ingår i den öppnade strukturen
            if (SelectedPath.Contains(data.NodePath) && data.NodeId != SelectedId)
            {
                LI.Attributes["class"] += " expanded";
                DIV.Attributes["class"] += " open";
            }
            
            
            DIV.Controls.Add(HA);
            LI.Controls.Add(DIV);

            //|| SelectedPath.Remove(SelectedPath.LastIndexOf("/")).Contains(q.NodePath.Remove(q.NodePath.LastIndexOf("/")))
            //SelectedPath.Contains(q.NodePath.Remove(q.NodePath.LastIndexOf("/")))
            foreach (_MenuData row in MenuData.Where(q => 
                (q.NodeParentId == parentId &&  q.NodeParentId == SelectedId)
                ||
                (q.NodeParentId == parentId && SelectedPath.Contains(q.NodePath))
                //Typ som publech
                ||
                (q.NodeParentId == parentId && SelectedPath.Remove(SelectedPath.LastIndexOf("/")).Equals(q.NodePath.Remove(q.NodePath.LastIndexOf("/"))))
                //Öppnar valt träd till viss nivå
                ||
                (q.NodeLevel <= HideAfterLevel && q.NodeParentId == parentId && SelectedPath.Contains(q.NodePath.Remove(q.NodePath.LastIndexOf("/")))) //Man får med första undernivån här därför att den blir ROOT
                ))
            {
                UL.Controls.Add(PopulateMenuItems(row, row.NodeId, UL, DIV, LI));
            }

            if(UL.Controls.Count > 0)
                LI.Controls.Add(UL);

            return LI;
        }



        protected override void Render(HtmlTextWriter writer)
        {
            LoadMenu();
            this.RenderContents(writer);
        } 

        public void RaisePostBackEvent(string eventArgument)
        {
            
            SelectedPath = eventArgument;
            SetSelectedProperties();

            if (Click != null)
            {
                Click(this, new EventArgs());
            }

            LoadMenu();
        }
    }
}
